package cz.cvut.manatee.processManager;

import java.util.LinkedList;
//import java.util.Collections;

public class QueryQueue {
	/*
	 * synchronizovany wrapped LinkedList haze nejakou vyjimku
	 * http://java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedList%28java.util.List%29
	 */
	private volatile LinkedList<Query> queue = (LinkedList<Query>) /*Collections.synchronizedList*/( new LinkedList<Query>() );
	
	
	/*
	 * Prida dotaz do fronty a overi, zda je ve stavu "cekani na vypocet"
	 */
	public synchronized void add(Query dotaz) throws AddingNotWaitingQueryException, AddingEmptyQueryException {
		if (dotaz == null) throw new AddingEmptyQueryException();
		if (dotaz.getState() != QueryState.WAITING) throw new AddingNotWaitingQueryException();
		
		this.queue.addLast(dotaz);
		System.out.println("Pridano "+dotaz+". "+this);
	}
	
	
	/*
	 * Odebere dotaz z fronty
	 */
	public synchronized void remove(Query dotaz) throws RemovingNotFinishedQueryFromQueueException {
		if (dotaz.getState() != QueryState.SOLVED) throw new RemovingNotFinishedQueryFromQueueException();
		
		this.queue.remove(dotaz);
		System.out.println("Odebrano "+dotaz+". "+this);
	}
	
	
	public synchronized void removeForce(Query dotaz) {
		this.queue.remove(dotaz);
	}
	
	
	/*
	 * Spocita pocet dotazu ve fronte s urcenym stavem.
	 * Pro vnitrni pouziti.
	 */
	protected synchronized int countQueries(QueryState stav) {
		int count = 0;
		
		for (Query q : this.queue) {
			if (q.getState() == stav) count++;
		}
		
		return count;
	}
	

	/*
	 * Vrati pole dotazu s vybranym stavem.
	 * Pro vnitrni pouziti.
	 */
	protected synchronized Query[] getQueries(QueryState stav) {
		int count = this.countQueries(stav);
		if (count > 0) {
			Query[] result = new Query[count];
			
			int i = 0;
			for (Query q : this.queue) {
				if (q.getState() == stav) result[i++] = q;
			}
			return result;
		}
		
		return null;
	}

	/*
	 * Vrati nejstarsi dotaz s vybranym stavem.
	 * Pro vnitrni pouziti.
	 */
	protected synchronized Query getLastQuery(QueryState stav) {
		if (this.countQueries(stav) > 0) {
			for (Query q : this.queue) {
				if (q.getState() == stav) return q;
			}
		}
		return null;
	}
	
	
	/*
	 * Pole dotazu cekajicich na zpracovani
	 */
	public synchronized Query[] getWaitingQueries() {
		return this.getQueries(QueryState.WAITING);
	}
	
	
	/*
	 * Pole spustenych dotazu
	 */
	public synchronized Query[] getExecutingQueries() {
		return this.getQueries(QueryState.EXECUTING);
	}
	
	
	/*
	 * Pole dokoncenych dotazu
	 */
	public synchronized Query[] getSolvedQueries() {
		return this.getQueries(QueryState.SOLVED);
	}

	/*
	 * Nejstersi dotazu cekajicich na zpracovani
	 */
	public synchronized Query getLastWaitingQuery() {
		return this.getLastQuery(QueryState.WAITING);
	}
	
	public synchronized void reset() {
		this.queue.clear();
	}
	
	/*
	 * Vypisuje pocet polozek
	 */
	public String toString() {
		return "Fronta dotazu obsahuje "+this.queue.size();
	}
}
